import { outlineItemType } from '../../types'
export const MarkdownParser = function (mdString: string): {
  content: string
  outline: outlineItemType[]
} {
  const lineList = mdString.split('\n')
  const outlineList: outlineItemType[] = []
  let startUnderline = false
  let startOrderedList = false
  let startQuote = false
  const newlineList = lineList.map((line, index) => {
    // 前缀标签
    let preTag: string = ''
    // 加粗
    line = parseBoldMarkdown(line)
    // 斜体
    line = parseMarkdownItalics(line)
    // 删除线
    line = parseStrikethrough(line)
    // 行内代码
    line = parseInlineCode(line)
    // 标题
    if (line.startsWith('#')) {
      const resultTemp = parseMarkdownHeadings(line, index)
      if (resultTemp) {
        line = resultTemp.content
        outlineList.push({
          ...resultTemp.outline,
          index
        })
      }
    }
    // 图片
    if (line.startsWith('![')) {
      line = mdImageToHtml(line)
    }
    // 链接
    line = convertMdLinksToHtml(line)
    // 待办
    if (line.startsWith('- [')) {
      line = convertTodoMarkdownToHtml(line, index)
    }
    // 引用
    if (line.startsWith('> ')) {
      if (startQuote) {
        line = parseQuote(line)
      } else {
        line = '<blockquote>' + parseQuote(line)
      }
      startQuote = true
    } else {
      if (startQuote) {
        preTag = '</blockquote>'
      }
      startQuote = false
    }
    // 无序列表
    if (line.startsWith('- ')) {
      if (startUnderline) {
        // 若之前是无序列表，直接添加列表项
        line = parseUnorderedList(line)
      } else {
        // 若之前不是无序列表，则开头添加'<ul>'
        line = '<ul>' + parseUnorderedList(line)
      }
      startUnderline = true
    } else {
      if (startUnderline) {
        preTag = '</ul>'
      }
      startUnderline = false
    }
    // 有序列表
    if (/^\d+\.\s+/.test(line)) {
      if (startOrderedList) {
        // 若之前是有序列表，直接添加列表项
        line = parseOrderedList(line)
      } else {
        // 若之前不是有序列表，则开头添加'<ol>'
        line = '<ol>' + parseOrderedList(line)
      }
      startOrderedList = true
    } else {
      // 若之前是有序列表，则结尾添加'</ol>'
      if (startOrderedList) {
        preTag = '</ol>'
      }
      startOrderedList = false
    }
    return preTag + line
  })
  let result = newlineList.join('\n')
  // 解析代码块
  result = parseCodeBlocks(result)
  // 解析表格
  result = parseTable(result)
  return {
    content: result,
    outline: outlineList
  }
}
/**
 * 将 Markdown 标题（# 开头）转换为 HTML 标题标签
 * @param markdown - 输入的 Markdown 文本
 * @returns 转换后的 HTML 文本
 */
function parseMarkdownHeadings(
  markdown: string,
  index: number
): {
  content: string
  outline: outlineItemType
} | void {
  // 正则表达式匹配 Markdown 标题
  const headingRegex = /^(#+)\s+(.*)$/gm
  const match = headingRegex.exec(markdown)
  if (match) {
    const level = match[1].length // 标题等级由#的数量决定
    const text = match[2].trim()
    const id = index.toString() // 生成锚点ID
    return {
      content: `<h${level}  id=${id}  >${escapeHTML(text)}</h${level}>`,
      outline: {
        text,
        id,
        level
      }
    }
  }
}
// 解析 Markdown 加粗语法为 HTML
function parseBoldMarkdown(markdown: string): string {
  // 正则表达式匹配 **粗体** 和 __粗体__
  const boldRegex = /(\*\*|__)(.*?)\1/g
  return markdown.replace(boldRegex, (_match, _delimiter, content) => {
    // 将匹配到的内容转换为 HTML 标签
    return `<strong>${escapeHTML(content)}</strong>`
  })
}
/**
 * 将 Markdown 斜体语法 (*text* 或 _text_) 解析为 HTML
 * @param markdown Markdown 文本
 * @returns 转换后的 HTML 文本
 */
function parseMarkdownItalics(markdown: string): string {
  // 处理 *text* 格式的斜体 (改进版本，处理嵌套星号)
  const asteriskRegex = /(?<!\*)\*(?!\*)([\s\S]*?)(?<!\*)\*(?!\*)/g
  const withAsterisks = markdown.replace(asteriskRegex, '<em>$1</em>')
  // 处理 _text_ 格式的斜体 (需要避免与下划线单词冲突)
  const underscoreRegex = /(?<!_)(?<!\w)_(?!_)([\s\S]*?)(?<!_)(?!\w)_(?!_)/g
  return withAsterisks.replace(underscoreRegex, '<em>$1</em>')
}
// 解析 Markdown 删除线语法为 HTML
function parseStrikethrough(mdText: string): string {
  // 正则表达式用于匹配 Markdown 删除线语法 (~~text~~)
  const strikethroughRegex = /~~([^~]+)~~/g
  // 使用 replace 方法将匹配到的删除线语法转换为 HTML 的 <s> 标签
  return mdText.replace(strikethroughRegex, '<s>$1</s>')
}
//解析 Markdown 无序列表语法为 HTML
function parseUnorderedList(mdText: string): string {
  return mdText.replace(/^([-+*])\s+(.*)$/g, '<li>$2</li>')
}
//解析 Markdown 有序列表语法为 HTML
function parseOrderedList(mdText: string): string {
  // 匹配以数字加 . 开头的有序列表项
  return mdText.replace(/^(\d+)\.\s+(.*)$/g, '<li>$2</li>')
}
//解析 Markdown 引用语法为 HTML
function parseQuote(mdText: string): string {
  // 正则表达式匹配引用行
  const quoteRegex = /^>\s*(.*)$/gm
  // 移除每行开头的 > 符号并转义 HTML 特殊字符
  const content = mdText.replace(quoteRegex, (_match, content) => {
    return escapeHTML(content)
  })
  return `<p>${content}</p>`
}
/**
 * 转义 HTML 特殊字符
 */
function escapeHTML(text: string): string {
  return text
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;')
}
/**
 * 将 Markdown 格式的超链接转换为 HTML 格式
 * @param mdText 包含 Markdown 超链接的文本
 * @returns 转换后的 HTML 文本
 */
function convertMdLinksToHtml(mdText: string): string {
  // 匹配 Markdown 超链接的正则表达式
  const mdLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g
  // 替换所有匹配到的 Markdown 超链接为 HTML 超链接
  return mdText.replace(mdLinkRegex, (_, text, url) => {
    // 构建 HTML 超链接
    return `<a href="${url}">${text}</a>`
  })
}
// 将 Markdown 待办列表解析为 HTML
function convertTodoMarkdownToHtml(mdText: string, index: number): string {
  // 定义待办列表的正则表达式
  const todoRegex = /^(\s*)- \[([ xX])\] (.*)$/gm
  // 使用 replace 方法进行转换
  return mdText.replace(todoRegex, (_match, indent, status, content) => {
    const isChecked = status.trim().toLowerCase() === 'x'
    const checkbox = isChecked ? `<input type="checkbox" checked >` : '<input type="checkbox" >'
    return `${indent}<label data-line_index=${index}  class="todo-item">${checkbox} ${content}</label>`
  })
}
/**
 * 将 Markdown 表格解析为 HTML 表格
 * @param mdText 包含表格的 Markdown 文本
 * @returns HTML 表格字符串
 */
function parseTable(mdText: string): string {
  // 替换表格
  mdText = mdText.replace(
    /^\|.*\|$\n^\|(?:-+:?|:-+:?|:?-+)\|.*\|$\n(?:^\|.*\|$\n?)+/gm,
    (match) => {
      return parseMarkdownTable(match)
    }
  )
  return mdText
}
// 解析行内代码
function parseInlineCode(mdText: string): string {
  const inlineCodeRegex = /`([^`]+)`/g
  return mdText.replace(inlineCodeRegex, '<code>$1</code>')
}
// 解析代码块
function parseCodeBlocks(mdText: string): string {
  // 处理标准代码块 (```)
  const fencedCodeBlockRegex = /```(?:(\w+)\n)?([\s\S]*?)```/g
  mdText = mdText.replace(fencedCodeBlockRegex, (_match, language, content) => {
    const codeContent = escapeHTML(content.trim())
    if (language) {
      return `<pre><code class="language-${language}">${codeContent}</code></pre>`
    }
    return `<pre><code>${codeContent}</code></pre>`
  })
  return mdText
}
// 解析 Markdown 表格为 HTML 表格
function parseMarkdownTable(mdTable: string): string {
  // 按行分割并过滤空行
  const lines = mdTable
    .split('\n')
    .map((line) => line.trim())
    .filter((line) => line.startsWith('|') && line.endsWith('|'))
  if (lines.length < 2) return ''
  // 解析表头
  const headerLine = lines[0]
  const headers = headerLine
    .split('|')
    .slice(1, -1)
    .map((cell) => cell.trim())
  // 解析分隔线，确定对齐方式
  const separatorLine = lines[1]
  const alignments = separatorLine
    .split('|')
    .slice(1, -1)
    .map((part) => {
      part = part.trim()
      if (part.startsWith(':') && part.endsWith(':')) return 'center'
      if (part.endsWith(':')) return 'right'
      return 'left'
    })
  // 解析内容行
  const rows = lines.slice(2).map((line) => {
    return line
      .split('|')
      .slice(1, -1)
      .map((cell) => cell.trim())
  })
  // 生成 HTML
  let html = '<table class="markdown-table">'
  // 表头
  html += '<thead><tr>'
  headers.forEach((header, index) => {
    const align = alignments[index] || 'left'
    html += `<th class="align-${align}">${header}</th>`
  })
  html += '</tr></thead>'
  // 表体
  html += '<tbody>'
  rows.forEach((row) => {
    html += '<tr>'
    row.forEach((cell, index) => {
      const align = alignments[index] || 'left'
      html += `<td align="${align}">${cell}</td>`
    })
    html += '</tr>'
  })
  html += '</tbody></table>'
  return html
}
/**
 * 将 Markdown 格式的图片转换为 HTML 格式
 * @param md 包含图片的 Markdown 文本
 * @returns 转换后的 HTML 文本
 */
function mdImageToHtml(md: string): string {
  // 匹配普通图片语法: ![替代文本](图片路径 "可选标题")
  const imageRegex = /!\[(.*?)\]\((.*?)(?:\s+"(.*?)")?\)/g
  // 匹配嵌套在链接中的图片语法: [![替代文本](图片路径 "可选标题")](链接地址)
  const linkedImageRegex = /\[!\[(.*?)\]\((.*?)(?:\s+"(.*?)")?\)\]\((.*?)\)/g
  // 先处理嵌套在链接中的图片
  let result = md.replace(linkedImageRegex, (_, alt, src, title, href) => {
    const imgTag = createImgTag(alt, src, title)
    return `<a href="${escapeHTML(href)}">${imgTag}</a>`
  })
  // 再处理普通图片
  result = result.replace(imageRegex, (_, alt, src, title) => {
    return createImgTag(alt, src, title)
  })
  return result
}
// 辅助函数：创建 img 标签
function createImgTag(alt: string, src: string, title?: string): string {
  const escapedSrc = escapeHTML(src)
  const escapedAlt = escapeHTML(alt)
  const titleAttr = title ? ` title="${escapeHTML(title)}"` : ''
  return `<img src="${escapedSrc}" alt="${escapedAlt}"${titleAttr}>`
}
